<template>
  <div class="o-filter-input" :style="filterStyle">
    <div class="btns">
      <ButtonGroup size="small">
        <Button @click="allSelect" type="text">
          {{ $srv.getI18nByPath('others.selectall') }}
        </Button>
        <Button @click="notAllSelect" type="text">
          {{ $srv.getI18nByPath('others.nselectall') }}
        </Button>
        <Button @click="reverseSelect" type="text">
          {{ $srv.getI18nByPath('others.rselect') }}
        </Button>
      </ButtonGroup>
    </div>
    <div class="search-key">
      <!-- @on-change="singlesFilter" -->
      <Input
        v-model="searchKey"
        icon="ios-search-outline"
        :placeholder="$srv.getI18nByPath('others.entersearch')"
        clearable
        @on-enter="handleSearchEnder"
        @on-clear="handleSearchClear"
      />
    </div>
    <div class="y-scroll checks">
      <div
        v-for="s in singles"
        :key="s.label"
        :title="isI18n ? $srv.getI18nBySrv(s.label) : s.label"
      >
        <Checkbox
          class="chk"
          v-show="s.isShow"
          v-model="s.isChk"
          @on-change="onsinglesChange"
        >
          {{ isI18n ? $srv.getI18nBySrv(s.label) : s.label }}
        </Checkbox>
      </div>
    </div>
    <div class="page">
      <div
        :class="{ arrow: true, disabled: currentPage < 2 }"
        @click="handleArrow(-1)"
      >
        <Icon type="ios-arrow-back" />
      </div>
      <div class="page-number">
        <InputNumber
          @on-change="handlePageNoChange"
          v-model="currentPage"
          :max="maxPage"
          :min="1"
        />
      </div>
      <div
        :class="{ arrow: true, disabled: currentPage >= maxPage }"
        @click="handleArrow(1)"
      >
        <Icon type="ios-arrow-forward" />
      </div>
      <div class="page-size">
        <Select v-model="pageSize" @on-change="handlePageSizeChange(false)">
          <Option
            v-for="itm in pageSizeOpts"
            :value="itm.value"
            :key="itm.value"
            >{{ itm.label }}</Option
          >
        </Select>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { Tsrv } from '@/services';
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';

@Component
export default class oFilterInput extends Vue {
  public compName: string = 'oFilterInput';

  @Prop() params: any;

  private searchKey = '';

  private singles = [];

  private column = null;

  private shouEd = false;

  private option = null;

  private type = 'string';

  private renderType = 'string';

  private condition = '=';

  private loading = false;

  private list = [];

  private selectedList = [1, 2, 3];

  private value = null;

  private filterStyle = {};

  // 获取列表接口参数
  private currentPage: number = 1;

  private pageSize: number = null;

  private pageTotal: number = 1;

  private filterListCondition: any = {};

  private total: number = 0;

  private pageSizeOpts: Array<any> = [
    {
      value: 10,
      label: `10${Tsrv.getI18nByValue('条')}/${Tsrv.getI18nByValue('页')}`
    },
    {
      value: 20,
      label: `20${Tsrv.getI18nByValue('条')}/${Tsrv.getI18nByValue('页')}`
    },
    {
      value: 30,
      label: `30${Tsrv.getI18nByValue('条')}/${Tsrv.getI18nByValue('页')}`
    },
    {
      value: 100,
      label: `100${Tsrv.getI18nByValue('条')}/${Tsrv.getI18nByValue('页')}`
    },
    {
      value: 200,
      label: `200${Tsrv.getI18nByValue('条')}/${Tsrv.getI18nByValue('页')}`
    },
    {
      value: 500,
      label: `500${Tsrv.getI18nByValue('条')}/${Tsrv.getI18nByValue('页')}`
    },
    {
      value: 1000,
      label: `1000${Tsrv.getI18nByValue('条')}/${Tsrv.getI18nByValue('页')}`
    }
  ];

  private isI18n: boolean = false;

  get maxPage() {
    // if (this.total <= 300) {
    //   if (this.total === 0) {
    //     return 1;
    //   }
    //   return Math.ceil(this.total / this.pageSize);
    // }
    return this.pageTotal;
  }

  @Watch('params')
  onParamsChange() {
    this.load();
  }

  @Watch('params.column.property')
  onParamsChanges() {
    this.isI18n = this.params.column.params.isI18n;
    // 获取已缓存的数据
    this.initFilterInputData();
    this.getFilterList();
  }

  created() {
    this.init();
    this.load();
    this.isI18n = this.params.column.params.isI18n;
  }

  mounted() {
    // 获取已缓存的数据
    this.initFilterInputData();
    this.getFilterList();
    this.$nextTick(() => {
      this.updateInputStyle();
    });
    // if (this.searchKey === '' && !this.singles.some(el => el.isChk)) {
    //   this.singlesFilter();
    // }
  }

  private getFilterList() {
    // if (this.total <= 300 && this.params.column.params.filters.length > 0) {
    //   const filters = Tsrv.utils.clone(this.params.column.params.filters);
    //   const chunks = Tsrv.utils.chunk(filters, this.pageSize);
    //   if (Tsrv.noValue(chunks[this.currentPage - 1])) {
    //     this.singles = this.params.column.params.filters;
    //   } else {
    //     this.singles = chunks[this.currentPage - 1];
    //   }
    // } else {
    this.handleFilterConditionBySearchKey();
    const reqParama = {
      currentPage: this.currentPage,
      pageSize: this.pageSize,
      filter: Tsrv.utils.clone(this.filterListCondition)
    };
    this.params.column.params.filterListParams.currentPage =
      reqParama.currentPage;
    this.params.column.params.filterListParams.pageSize = reqParama.pageSize;
    this.params.column.params.filterListParams.searchKey = this.searchKey;

    this.params.column.params
      .loadFilterList(this.params.column.property, reqParama)
      .then(data => {
        this.loading = false;
        this.pageTotal = data?.pageTotal ?? 0;
        this.total = data?.total ?? 0;
        this.params.column.params.filterListParams.total = this.total;
        const list = data?.list;
        if (Tsrv.utils.isArray(list)) {
          this.list = list;
          Tsrv.utils.clear(this.singles);
          this.list.forEach(e => {
            const v: any = e.virtualValue ? e.virtualValue : e.value;
            this.singles.push({
              label: `${v}`,
              value: v,
              filterField: e.field,
              filterValue: e.value,
              isChk: false,
              isShow: true
            });
          });
          this.params.column.params.loadedFilterList = list;
          this.handleSinglesChkByfiltersSelected();
        }
        this.updateInputStyle();
      })
      .catch(() => {
        this.loading = false;
      });
    // }
  }

  private handleFilterConditionBySearchKey() {
    if (Tsrv.noValue(this.searchKey)) {
      this.filterListCondition = {};
    } else {
      this.filterListCondition = this.parseFilter(this.searchKey);
    }
  }

  private initFilterInputData() {
    const colParams = this.params.column.params;
    const filterListParams = colParams?.filterListParams;
    if (Tsrv.noValue(filterListParams)) {
      return;
    }
    const searchKey = filterListParams?.searchKey ?? '';
    const currentPage = filterListParams?.currentPage ?? 1;
    const pageSize = filterListParams?.pageSize ?? 30;
    const total = filterListParams?.total ?? 0;
    if (!Tsrv.noValue(searchKey)) {
      this.searchKey = searchKey;
    }
    if (!Tsrv.noValue(currentPage)) {
      this.currentPage = currentPage;
    }
    if (!Tsrv.noValue(pageSize)) {
      this.pageSize = pageSize;
    }
    if (!Tsrv.noValue(total)) {
      this.total = total;
    }
  }

  private handleSinglesChkByfiltersSelected() {
    const colParams = this.params.column.params;
    const filtersSelected = colParams?.filtersSelected;
    if (filtersSelected.length > 0) {
      this.singles.forEach(single => {
        const findIndex = filtersSelected.findIndex(
          t => t.filterValue === single.filterValue
        );
        if (findIndex > -1) {
          single.isChk = filtersSelected[findIndex].isChk;
        }
      });
    }
  }

  private handleSearchEnder() {
    this.currentPage = 1;
    this.getFilterList();
  }

  private handleSearchClear() {
    this.currentPage = 1;
    this.getFilterList();
  }

  private handlePageSizeChange(isAuto: boolean) {
    if (!isAuto) {
      this.currentPage = 1;
      this.getFilterList();
    }
  }

  private handlePageNoChange() {
    this.getFilterList();
  }

  private handleArrow(num: number) {
    const pn = this.currentPage + num;
    if (pn > 0 && pn < this.maxPage + 1) {
      this.currentPage = pn;
      this.getFilterList();
    }
  }

  beforeDestroy() {
    if (
      this.params.column.params.loadedFilterList &&
      this.params.column.params.loadedFilterList.length > 0
    ) {
      this.params.column.params.loadedFilterList = Tsrv.utils.clone(
        this.selectedList
      );
    }
  }

  /**
   * 根据 searchKey 即搜索框中的值 筛选可显示项
   */
  private singlesFilter() {
    if (this.searchKey === '') {
      this.singles.forEach(e => {
        e.isShow = true;
      });
    } else {
      this.singles.forEach(e => {
        if (Tsrv.getI18nBySrv(e.label).indexOf(this.searchKey) !== -1) {
          e.isShow = true;
        } else {
          e.isShow = false;
        }
      });
    }
  }

  /**
   * 更新字段筛选框高度
   */
  private updateInputStyle() {
    const parent = this.$el.parentElement;
    const filterContent = parent?.parentElement ?? null;
    const vxeTable: HTMLElement | null =
      parent?.parentElement?.parentElement ?? null;
    if (!Tsrv.noValue(filterContent) && !Tsrv.noValue(vxeTable)) {
      parent.style.maxHeight = `${vxeTable.offsetHeight - 68}px`;
      this.filterStyle = {
        maxHeight: parent.style.maxHeight
      };
    }
  }

  private allSelect() {
    this.singles.forEach(e => {
      // e.val = true;
      e.isChk = true;
    });
    this.onsinglesChange();
  }

  private notAllSelect() {
    this.singles.forEach(e => {
      // e.val = false;
      e.isChk = false;
    });
    this.params.column.params.filtersSelected = [];
    this.onsinglesChange();
  }

  private reverseSelect() {
    this.singles.forEach(e => {
      e.isChk = !e.isChk;
    });
    this.onsinglesChange();
  }

  onsinglesChange() {
    // this.params.column.params.filters = this.singles;
    // 选中取消勾选的 更新filtersSelected
    const colParams = this.params.column.params;
    const filtersSelected = colParams?.filtersSelected;
    this.singles.forEach(e => {
      const findKey = filtersSelected.findIndex(
        t => t.filterValue === e.filterValue
      );
      if (e.isChk) {
        if (findKey < 0) {
          filtersSelected.push(e);
        }
      } else {
        if (findKey > -1) {
          filtersSelected.splice(findKey, 1);
        }
      }
    });
    const isSelect = !!this.singles.find(ele => ele.isChk === true);
    this.params.$panel.changeOption(
      null,
      isSelect,
      this.params.column.filters[0]
    );
  }

  private changeCondition(con: any) {
    if (['datetime', 'date', 'time', 'number'].indexOf(this.type) > -1) {
      if (con === ':') {
        this.value = ['', ''];
        this.renderType = `${this.type}range`;
      } else {
        if (this.condition === ':') {
          this.renderType = this.type;
          this.value = '';
        }
      }
    }
    this.condition = con;
    this.changeOptionEvent();
  }

  private inputChange() {
    this.selectedList = [];
    this.params.column.params.loadedFilterList = [];
    this.changeOptionEvent();
  }

  private dateChange(value: any) {
    this.value = value;
    this.selectedList = [];
    this.params.column.params.loadedFilterList = [];
    this.changeOptionEvent();
  }

  /**
   * 该函数未被使用过
   */
  private loadMultiList() {
    if (
      (this.list.length === 0 ||
        this.selectedList.length === this.list.length) &&
      !this.loading
    ) {
      this.loading = true;
      this.params.column.params
        .loadFilterList(this.params.column.property)
        .then(data => {
          this.loading = false;
          this.pageTotal = data?.pageTotal ?? 0;
          const list = data?.list;
          if (Tsrv.utils.isArray(list)) {
            this.list = list;
            this.params.column.params.loadedFilterList = list;
          }
        })
        .catch(() => {
          this.loading = false;
        });
    }
    this.$nextTick(() => {
      this.updateInputStyle();
    });
  }

  private selectMultiList() {
    this.changeOptionEvent();
  }

  private init() {
    const { column } = this.params;
    const info = Tsrv.utils.getColumnType(column);
    if (info.name) {
      if (info.name === 'oDatePicker' || info.name === 'oNumberInput') {
        this.condition = '=';
      } else {
        this.condition = 'custom';
      }
      this.type = info.type;
      this.renderType = info.renderType;
    }
  }

  private load() {
    const { column } = this.params;
    const option = column.filters[0];
    this.column = column;
    this.option = option;

    const { data, list } = option;
    if (data) {
      this.condition = data.condition || '=';
      this.value = data.value;
      this.changeOptionEvent();
    }

    if (list) {
      this.selectedList = list;
    }

    this.list = this.params.column.params.loadedFilterList || [];
  }

  private replaceSensitive(value) {
    if (typeof value === 'string') {
      return (
        value
          .replace(/,/g, '\\,')
          .replace(/:/g, '\\:')
          // .replace(/\|/g, "\\|")
          .replace(/\*/g, '\\*')
      );
    }
    return value;
  }

  private changeOptionEvent() {
    const { params, option } = this;
    const { $panel } = params;
    option.advance = {};
    option.list = [];
    if (this.selectedList.length === 0) {
      option.data = {
        ...Tsrv.utils.valueToFilter(
          this.type,
          this.condition,
          this.value ? this.replaceSensitive(this.value) : this.value
        ),
        aas: 123
      };
      option.advance = Tsrv.utils.valueToFilter(
        this.type,
        this.condition,
        this.value
      );
    } else {
      option.data = {
        ...Tsrv.utils.valueToFilter(
          'string',
          'custom',
          this.selectedList
            .map(el => {
              return this.replaceSensitive(el);
            })
            .join('|')
        ),
        aas: 123
      };
      option.list = this.selectedList;
    }
    option.aas = '123';
    const checked = !!option.data;
    $panel.changeOption(null, checked, option);
  }

  private keyupEvent({ $event }) {
    const { params } = this;
    const { $panel } = params;
    if ($event.keyCode === 13) {
      $panel.confirmFilter();
    }
  }

  /**
   * 获取 请求列表接口 的参数
   */
  private handleGetListParams() {
    return {
      pageNo: this.currentPage,
      pageSize: this.pageSize,
      searchKey: this.searchKey
    };
  }

  // searchKey的转换

  /**
   * 将通配符模式转换为正则表达式字符串
   * @param pattern 输入的通配符模式
   * @returns 处理后的正则表达式字符串，或 null（当模式无效时）
   */
  private buildRegexPattern(pattern: string): string | null {
    const r = wQBEToSQLRegexp(pattern);
    if (r.isErr()) {
      throw new Error(r.getErrMsg());
    }
    return r.getReturnData('data');
  }

  /**
   * 将通配符查询字符串转换为 MongoDB 查询对象
   * @param input 包含通配符模式的字符串（多个模式用空格分隔）
   * @returns MongoDB 查询对象
   */
  private patternToQuery(input: string): Record<string, any> {
    // 要查询的字段名
    const field = this.params.column.property;
    if (!input || input.trim() === '') return {};

    // 分割多个模式（支持空格分隔），过滤空模式
    const patterns = input
      .trim()
      .split(/\s+/)
      .filter(p => p !== '');

    // 处理每个模式并收集有效结果
    const validPatterns = patterns
      .map(this.buildRegexPattern)
      .filter((regex): regex is string => regex !== null);

    // 如果没有有效模式，返回空对象
    if (validPatterns.length === 0) return {};

    // 单模式直接返回查询对象
    if (validPatterns.length === 1) {
      return { [field]: { $regex: validPatterns[0] } };
    }

    // 多模式返回 $or 查询
    return {
      $or: validPatterns.map(regex => ({
        [field]: { $regex: regex }
      }))
    };
  }

  private parseFilter(input: string): Record<string, any> {
    // 是否需要向后端请求
    // if (this.filterListParams.total - this.filterListParams.pageSize*this.filterListParams.currentPage <= this.filterListParams.pageSize)

    // 要查询的字段名
    if (!input || input.trim() === '') return null;
    const isSlc = !Tsrv.noValue(this.column.params.source.selectionID);
    const isM2o =
      !Tsrv.noValue(this.column.params.source.many2one.toField) ||
      !Tsrv.noValue(this.column.params.source.many2one.toTable);
    const isSubQry = !Tsrv.noValue(this.column.params.source.many2one.subQuery);
    if (!isM2o && !isSlc && !isSubQry && !this.isI18n) {
      return this.patternToQuery(input);
    }

    let stdFieldName = this.params.column.property;
    let fieldName = this.params.column.property;
    if (this.params.column.property.split('|').length >= 3) {
      stdFieldName = this.params.column.property;
    } else if (isSlc) {
      stdFieldName = `\`slc|${this.params.column.property}|${this.column.params.source.selectionID}\``;
      fieldName = stdFieldName;
    } else if (isM2o) {
      stdFieldName = `\`m2o|${this.params.column.property}|${this.column.params.source.many2one.toTable}|${this.column.params.source.many2one.toField}\``;
      fieldName = stdFieldName;
    }
    for (const ele of this.list.filter(el => {
      return el.filed === stdFieldName || el.virtualField === stdFieldName;
    })) {
      if (ele.virtualField.length > 0) {
        stdFieldName = ele.virtualField;
        break;
      }
    }
    // N_oBaseGrid.I_fieldFilter
    return {
      fieldName,
      stdFieldName,
      isI18n: this.isI18n,
      isSlc,
      isM2o,
      isSubQry,
      pattern: input.split(' ')
    };
  }
}
</script>

<style lang="scss" scoped>
.o-filter-input {
  padding: 6px;
  max-width: 240px;
  min-width: 200px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  .btns {
    border-bottom: 1px solid #cccccc;
    width: 100%;
    text-align: center;
    padding: 5px 0px;
  }
  .search-key {
    width: 100%;
    ::v-deepinput {
      border-radius: unset;
    }
  }
  .checks {
    padding: 0px 15px;
    flex: 1;
    .chk {
      margin: 6px 0px;
      overflow: hidden;
      text-overflow: ellipsis;
      width: 100%;
      white-space: nowrap;
    }
  }
  .page {
    // display: flex;
    // flex-direction: row;
    // justify-content: space-around;
    // align-items: center;
    display: grid;
    grid-template-columns: 1fr 2fr 1fr 2fr;
    grid-template-rows: 1fr;
    justify-content: space-around;
    align-items: center;
    padding-top: 5px;
    gap: 5px;
    // padding: 0 15px;
    div {
      height: 100%;
      width: 100%;
    }

    .arrow {
      display: flex;
      justify-content: center;
      align-items: center;
      display: grid;
      border: 1px solid #ccc;
      border-radius: 5px;
      height: 100%;
      &:hover {
        cursor: pointer;
        border: 1px solid #2d8eff;
      }
    }

    .disabled {
      color: #ccc;
      &:hover {
        cursor: not-allowed;
        border: 1px solid #ccc;
      }
    }
  }
  .filter-multi {
    padding-bottom: 5px;
    ::v-deep .ivu-select {
      .ivu-select-selection {
        max-height: 140px;
        overflow-y: auto;
        &::-webkit-scrollbar {
          width: 6px;
          background: #f5f5f5;
          border-radius: 6px;
        }
        &::-webkit-scrollbar-track-piece {
          background: #fff;
          border-radius: 6px;
        }
        &::-webkit-scrollbar-thumb {
          background: #b1b1b1;
          border-radius: 6px;
        }
      }
    }
  }
  .title {
    padding: 5px 0;
    color: #999;
  }
  .filters {
    width: 220px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    height: 100%;
    padding-bottom: 5px;
    .ivu-radio-group ::v-deep {
      .ivu-radio-inner::after {
        border-radius: 100%;
      }
    }
    .ivu-input-wrapper,
    .ivu-date-picker {
      margin-top: 10px;
    }
  }
}
</style>
